
local RUtil = require 'packages/aaa_fenghou/utility/_base'

local U = require "packages/utility/utility"

--- 重新隐匿
---@param player ServerPlayer @ 目标角色
RUtil.EnterHidden = function (player)
  local room = player.room
  room:sendLog({
    type = "#rfenghouEnterHidden",
    from = player.id,
  })
  local skills = "hidden_skill&"
  room:setPlayerMark(player, "__hidden_general", player.general)
  for _, s in ipairs(Fk.generals[player.general]:getSkillNameList(true)) do
    if player:hasSkill(s, true) then
      skills = skills.."|-"..s
    end
  end
  if player.deputyGeneral ~= "" then
    room:setPlayerMark(player, "__hidden_deputy", player.deputyGeneral)
    for _, s in ipairs(Fk.generals[player.deputyGeneral]:getSkillNameList(true)) do
      if player:hasSkill(s, true) then
        skills = skills.."|-"..s
      end
    end
  end
  player.general = "hiddenone"
  player.gender = General.Male
  room:broadcastProperty(player, "gender")
  if player.deputyGeneral ~= "" then
    player.deputyGeneral = ""
  end
  player.kingdom = "jin"
  room:setPlayerMark(player, "__hidden_record",
  {
    maxHp = player.maxHp,
    hp = player.hp,
  })
  player.maxHp = 1
  player.hp = 1
  for _, property in ipairs({"general", "deputyGeneral", "kingdom", "maxHp", "hp"}) do
    room:broadcastProperty(player, property)
  end
  room:handleAddLoseSkills(player, skills, nil, false, true)
end
Fk:loadTranslationTable{
  ["#rfenghouEnterHidden"] = "%from 进入隐匿状态",
  ["rfenghou__enterhidden"] = "记录当前的体力上限和体力值，失去当前武将牌上的所有技能，将武将替换为隐匿将。再次登场后，"..
  "将体力上限和体力值调整为记录值，武将替换回隐匿前的武将，获得武将牌上所有的技能。",
}

local enter_hidden_trigger = fk.CreateTriggerSkill{
  name = "#enter_hidden_trigger",
  priority = 0.001,
  global = true,

  refresh_events = {fk.GamePrepared},
  can_refresh = function (self, event, target, player, data)
    return true
  end,
  on_refresh = function (self, event, target, player, data)
    local room = player.room
    if player.seat == 1 and room.settings.gameMode ~= "new_heg_mode" then  --祭祀智慧，诸葛连弩换+3弩
      for i = #room.draw_pile, 1, -1 do
        local id = room.draw_pile[i]
        if Fk:getCardById(id).name == "crossbow" then
          table.insert(room.void, id)
          room:setCardArea(id, Card.Void, nil)
          local new_card = room:printCard("xbow", Fk:getCardById(id).suit, Fk:getCardById(id).number)
          room.draw_pile[i] = new_card.id
          room:setCardArea(new_card.id, Card.DrawPile, nil)
        end
      end
    end
    if player.general ~= "hiddenone" and table.find(player.player_skills, function (s)  --祭祀智慧，非身份局也要隐匿
      return s.isHiddenSkill and
        not (s.name == "rfenghou__renru" and table.contains({"m_1v2_mode", "brawl_mode"}, room.settings.gameMode))  --哈哈，若制
    end) then
      RUtil.EnterHidden(player)
    end
  end,
}
Fk:addSkill(enter_hidden_trigger)

--新系统 蓄势技
local ready_skill = fk.CreateActiveSkill{
  name = "rfenghou_ready_skill&",
  prompt = "#rfenghou_ready_skill&",
  anim_type = "special",
  card_num = 3,
  target_num = 0,
  interaction = function(self)
    local skills = {}
    for _, s in ipairs(Self.player_skills) do
      if Self:getMark("@@rfenghou_readying:::"..s.name) > 0 and Self:usedSkillTimes(s.name, Player.HistoryRound) == 0 then
        table.insert(skills, s.name)
      end
    end
    return UI.ComboBox { choices = skills }
  end,
  can_use = function(self, player)
    return table.find(player.player_skills, function(s)
      return player:getMark("@@rfenghou_readying:::"..s.name) > 0 and player:usedSkillTimes(s.name, Player.HistoryRound) == 0
    end)
  end,
  card_filter = function(self, to_select, selected)
    return #selected < 3 and not Self:prohibitDiscard(to_select)
  end,
  on_use = function(self, room, effect)
    local player = room:getPlayerById(effect.from)
    room:throwCard(effect.cards, self.name, player, player)
    if not player.dead then
      room:setPlayerMark(player, "@@rfenghou_readying:::"..self.interaction.data, 0)
      local data = Fk.skills[self.interaction.data]
      room.logic:trigger("fk.RfenghouSkillReady", player, data, false)
    end
  end,
}
local ready_skill_trigger = fk.CreateTriggerSkill{
  name = "#ready_skill_trigger",
  priority = 0.001,
  global = true,

  refresh_events = {fk.EventAcquireSkill, fk.EventLoseSkill, fk.AfterSkillEffect, fk.AfterDrawPileShuffle, fk.GamePrepared},
  can_refresh = function (self, event, target, player, data)
    if event == fk.AfterDrawPileShuffle then
      return table.find(player.player_skills, function(s)
        return player:getMark("@@rfenghou_readying:::"..s.name) > 0
      end)
    elseif event == fk.GamePrepared then
      -- 注意，全局触发技能添加到游戏比角色技能晚，无法检测开局添加的角色技能
      return not player:hasSkill("rfenghou_ready_skill&", true) and table.find(player.player_skills, function (s)
        return s.RfenghouReadySkill
      end)
    else
      return target == player and data.RfenghouReadySkill
    end
  end,
  on_refresh = function (self, event, target, player, data)
    local room = player.room
    if event == fk.AfterDrawPileShuffle then
      for _, s in ipairs(player.player_skills) do
        if player:getMark("@@rfenghou_readying:::"..s.name) > 0 then
          room:setPlayerMark(player, "@@rfenghou_readying:::"..s.name, 0)
          room.logic:trigger("fk.RfenghouSkillReady", player, s, false)
        end
      end
    elseif event == fk.EventAcquireSkill or event == fk.GamePrepared then
      room:handleAddLoseSkills(player, "rfenghou_ready_skill&", nil, false, true)
    elseif event == fk.EventLoseSkill then
      room:setPlayerMark(player, "@@rfenghou_readying:::"..data.name, 0)
      if not table.find(player.player_skills, function (s)
        return s.RfenghouReadySkill
      end) then
        room:handleAddLoseSkills(player, "-rfenghou_ready_skill&", nil, false, true)
      end
    elseif event == fk.AfterSkillEffect then
      room:setPlayerMark(player, "@@rfenghou_readying:::"..data.name, 1)
      room.logic:trigger("fk.RfenghouSkillNulli", player, data, false)
    end
  end,
}
Fk:addSkill(ready_skill)
Fk:addSkill(ready_skill_trigger)
Fk:loadTranslationTable{
  ["rfenghou_ready_skill&"] = "蓄势技",
  [":rfenghou_ready_skill&"] = "出牌阶段，你可以弃置三张牌，重置一个本轮未发动过的蓄势技。",
  ["#rfenghou_ready_skill&"] = "你可以弃置三张牌，重置一个本轮未发动过的蓄势技",
  ["rfenghou_ready_skill"] = "一种技能标签，拥有此标签的技能发动后失效，直到牌堆洗切后重置；出牌阶段，你可以弃置三张牌，"..
  "重置一个本轮未发动过的蓄势技。",
}

--[[
  手牌监控器
  用于检测角色的手牌数是否变为最大、唯一最大、最小、唯一最小、失去最后手牌
--]]
local handcardnum_monitor = fk.CreateTriggerSkill{
  name = "#handcardnum_monitor",
  global = true,

  refresh_events = {fk.AfterCardsMove, fk.GameStart},
  can_refresh = function (self, event, target, player, data)
    if player.seat ~= 1 then return false end
    if event == fk.GameStart then return true end
    for _, move in ipairs(data) do
      if move.toArea == Player.Hand then return true end
      for _, info in ipairs(move.moveInfo) do
        if info.fromArea == Player.Hand then
          return true
        end
      end
    end
  end,
  on_refresh = function (self, event, target, player, data)
    local room = player.room
    local oldEmpty, oldMax, oldMin = room:getTag("hcnm_empty") or {}, room:getTag("hcnm_max") or {}, room:getTag("hcnm_min") or {}
    local newEmpty, newMax, newMin = {}, {}, {}
    local minNum, maxNum = 9999, 0
    for _, p in ipairs(room.alive_players) do
      if p:isKongcheng() then
        table.insert(newEmpty, p.id)
      end
      minNum = math.min(minNum, p:getHandcardNum())
      maxNum = math.max(maxNum, p:getHandcardNum())
    end
    for _, p in ipairs(room.alive_players) do
      if p:getHandcardNum() == minNum then
        table.insert(newMin, p.id)
      end
      if p:getHandcardNum() == maxNum then
        table.insert(newMax, p.id)
      end
    end
    room:setTag("hcnm_empty", newEmpty)
    room:setTag("hcnm_max", newMax)
    room:setTag("hcnm_min", newMin)
    local onlyMax, onlyMin = room:getTag("hcnm_onlyMax"), room:getTag("hcnm_onlyMin")
    local newOnlyMax = #newMax == 1 and newMax[1] or nil
    local newOnlyMin = #newMin == 1 and newMin[1] or nil
    room:setTag("hcnm_onlyMax", newOnlyMax)
    room:setTag("hcnm_onlyMin", newOnlyMin)
    if event ~= fk.AfterCardsMove then return end
    data.extra_data = data.extra_data or {}
    data.extra_data.hcnm_becomeEmpty = table.filter(newEmpty, function (id) return not table.contains(oldEmpty, id) end)
    data.extra_data.hcnm_becomeMax = table.filter(newMax, function (id) return not table.contains(oldMax, id) end)
    data.extra_data.hcnm_becomeMin = table.filter(newMin, function (id) return not table.contains(oldMin, id) end)
    if newOnlyMax ~= onlyMax then
      data.extra_data.hcnm_becomeOnlyMax = newOnlyMax
    end
    if newOnlyMin ~= onlyMin then
      data.extra_data.hcnm_becomeOnlyMin = newOnlyMin
    end
  end,
}
Fk:addSkill(handcardnum_monitor)

--印影
RUtil.getShade = function (room, n)
  local ids = {}
  for _, id in ipairs(room.void) do
    if n <= 0 then break end
    if Fk:getCardById(id).name == "rfenghou__shade" then
      room:setCardMark(Fk:getCardById(id), MarkEnum.DestructIntoDiscard, 1)
      table.insert(ids, id)
      n = n - 1
    end
  end
  while n > 0 do
    local card = room:printCard("rfenghou__shade", Card.Spade, 1)
    room:setCardMark(card, MarkEnum.DestructIntoDiscard, 1)
    table.insert(ids, card.id)
    n = n - 1
  end
  return ids
end

--先把半成品蓄谋放在这里，祭祀智慧不想加jsrg……
---@param player ServerPlayer @ 操作蓄谋的玩家
---@param card integer | Card  @ 用来蓄谋的牌
---@param skill_name? string @ 技能名
---@param proposer? integer @ 移动操作者的id
---@return nil
RUtil.premeditate = function(player, card, skill_name, proposer)
  skill_name = skill_name or ""
  proposer = proposer or player.id
  local room = player.room
  if type(card) == "table" then
    assert(not card:isVirtual() or #card.subcards == 1)
    card = card:getEffectiveId()
  end
  local xumou = Fk:cloneCard("rfenghou__premeditate")
  xumou:addSubcard(card)
  room:sendLog{
    type = "#premeditate",
    from = proposer,
    to = {player.id},
  }
  player:addVirtualEquip(xumou)
  room:moveCardTo(xumou, Player.Judge, player, fk.ReasonJustMove, skill_name, nil, false, proposer, "", {proposer, player.id})
end

local premeditate_rule = fk.CreateTriggerSkill{
  name = "#rfenghou__premeditate_rule",
  events = {fk.EventPhaseStart},
  mute = true,
  global = true,
  priority = 0,
  can_trigger = function(self, event, target, player, data)
    return target == player and player.phase == Player.Judge
  end,
  on_cost = Util.TrueFunc,
  on_use = function(self, event, target, player, data)
    local room = player.room
    local cards = player:getCardIds(Player.Judge)
    for i = #cards, 1, -1 do
      if table.contains(player:getCardIds(Player.Judge), cards[i]) then
        if player.dead then return end
        local xumou = player:getVirualEquip(cards[i])
        if xumou and xumou.trueName == "premeditate" then
          local use = U.askForUseRealCard(room, player, {cards[i]}, ".", "premeditate",
            "#premeditate-use:::"..Fk:getCardById(cards[i], true):toLogString(),
            {expand_pile = {cards[i]}, extra_use = true}, true, true)
          if use then
            room:setPlayerMark(player, "premeditate_"..use.card.trueName.."-phase", 1)
            use.extra_data = use.extra_data or {}
            use.extra_data.premeditate = true
            room:useCard(use)
          else
            break
          end
        end
      end
    end
    cards = player:getCardIds(Player.Judge)
    local xumou = table.filter(cards, function(id)
      local card = player:getVirualEquip(id)
      return card and card.trueName == "rfenghou__premeditate"
    end)
    room:moveCardTo(xumou, Card.DiscardPile, nil, fk.ReasonPutIntoDiscardPile, "premeditate", nil, true, player.id)
  end,
}
local premeditate_prohibit = fk.CreateProhibitSkill{
  name = "#rfenghou__premeditate_prohibit",
  global = true,
  prohibit_use = function(self, player, card)
    return card and player:getMark("premeditate_"..card.trueName.."-phase") > 0
  end,
}
Fk:addSkill(premeditate_rule)
Fk:addSkill(premeditate_prohibit)
Fk:loadTranslationTable{
  ["#premeditate"] = "%from 对 %to 进行了蓄谋",
  ["#premeditate-use"] = "你可以使用此蓄谋牌%arg，或点“取消”将所有蓄谋牌置入弃牌堆",
}

--- 更改转换技标记，适用于3项以上的diy转换技
---@param player ServerPlayer @ 目标角色
---@param total integer @ 转换技总项数
RUtil.RfenghouSwitch = function (player, total)
  local room = player.room
  for i = 1, 999, 1 do
    if player:getMark("@!rfenghou"..i) > 0 then
      room:setPlayerMark(player, "@!rfenghou"..i, 0)
      if i < total then
        room:setPlayerMark(player, "@!rfenghou"..(i + 1), 1)
      else
        room:setPlayerMark(player, "@!rfenghou1", 1)
      end
      return
    end
  end
end

--- 移动某角色区域内一张牌
---@param from ServerPlayer @ 被移动牌的角色
---@param proposer ServerPlayer @ 操控者
---@param skillName string @ 技能名
---@param cancelable boolean @ 是否可取消，默认可取消
---@return integer|nil @ 被移动的牌id，可能为空
RUtil.askForMoveCardFromPlayerArea = function (from, proposer, skillName, cancelable)
  local room = from.room
  if from:isAllNude() or table.every(room.alive_players, function(p) return p == from end) then return end
  cancelable = cancelable == nil or cancelable
  local targets = table.filter(room.alive_players, function(p) return from:canMoveCardsInBoardTo(p, nil) end)
  local choices = {}
  if not from:isKongcheng() then table.insert(choices, "#RUtil_moveHand:"..from.id) end
  if #targets > 0 then table.insert(choices, "#RUtil_moveBoard:"..from.id) end
  if #choices == 0 then return end
  if cancelable then table.insert(choices, "Cancel") end
  local choice = room:askForChoice(proposer, choices, skillName)
  if choice == "Cancel" then return end
  if choice:startsWith("#RUtil_moveHand") then targets = room:getOtherPlayers(from, false) end
  local t = room:askForChoosePlayers(proposer, table.map(targets, Util.IdMapper), 1, 1, "#RUtil-moveCard:"..from.id, skillName, cancelable)
  if #t > 0 then
    if choice:startsWith("#RUtil_moveHand") then
      local cid = room:askForCardChosen(proposer, from, "h", skillName)
      room:obtainCard(t[1], cid, false, fk.ReasonJustMove, proposer.id, skillName)
      return cid
    else
      return room:askForMoveCardInBoard(proposer, from, room:getPlayerById(t[1]), skillName, nil, from, {}).card.id
    end
  end
end

Fk:loadTranslationTable{
  ["#RUtil_moveHand"] = "移动 %src 的手牌",
  ["#RUtil_moveBoard"] = "移动 %src 场上牌",
  ["#RUtil-moveCard"] = "选择获得 %src 的牌的角色",
}


return RUtil
